﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using PMC;
using PMC.Extensions;
using PMC.Extensions.Default;
using PMC.Interfaces;
using PMC.Structs;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;

namespace VacationExtension
{
    public class VacationExtension : IExtension
    {
        private BindingList<Website> websites;
        private string postdataFormat = "user_form=userinfo&userform%5Bvacation%5D={0}&userform%5Balterinfo_password%5D={1}";
        private List<string> relativeUris = new List<string> { "pages/userinfo.php", "pages/profile.php" };
        private string filename = PMC.Properties.Settings.Default.SettingsFolder + "/VacationExtension.xml";
        private bool changed;

        public void Process(DateTime date)
        {
            if (OnActivated())
                return;

            INotifyProgress progress = new ProgressForm();
            var thread = new Thread(c => PrivateProcess(date, progress)) { IsBackground = true, };
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        private void PrivateProcess(DateTime date, INotifyProgress progress)
        {
            double currentWebsite = 0;
            foreach (Website website in websites)
            {
                currentWebsite++;
                //var parsedDate = string.Format("{0:MM/dd/yyyy}", date).Replace("-", "%2F");
                var parsedDate = string.Format(CultureInfo.InvariantCulture, "{0:MM}%2F{0:dd}%2F{0:yyyy}", DateTime.Now);

                foreach (string relativeUri in relativeUris)
                {
                    var uri = new Uri(website.Webpage, relativeUri);
                    website.Login(relativeUri);

                    HtmlDocument document;
                    try
                    {
                        document = Global.HtmlUtility.HttpPageRequest(uri, "POST", string.Format(CultureInfo.InvariantCulture, postdataFormat, parsedDate, website.Password));
                    }
                    catch (WebException ex)
                    {
                        Log.Instance.AddException(ex);
                        continue;
                    }
                    if (document != null && document.DocumentNode.Descendants("input").Count() > 7)
                        break;
                }
                progress.NotifyProgress((int)(currentWebsite / websites.Count * 100));
            }
            progress.NotifyProgress(100);
            var disposeWindow = progress as IDisposable;
            if (disposeWindow != null)
                disposeWindow.Dispose();
            OnFinished();
        }

        #region Implementation of IExtension

        private VacationExtensionTabPage tab;
        public TabPage SettingsControl
        {
            get { return tab ?? (tab = new VacationExtensionTabPage(websites, this)); }
        }

        public event EventHandler Finished;
        public event CancelEventHandler Activated;
        public bool OnActivated()
        {
            if (Activated == null)
                return false;

            var cancel = new CancelEventArgs();
            Activated.Invoke(this, cancel);
            return cancel.Cancel;
        }

        public void OnFinished()
        {
            if (Finished == null)
                return;

            Finished.Invoke(this, EventArgs.Empty);
        }

        #endregion

        #region Implementation of ISaveloadable

        public bool Changed
        {
            get { return changed; }
        }

        public void Load()
        {
            try
            {
                if (!File.Exists(filename))
                    return;

                websites = Global.XMLDeserialize<BindingList<Website>>(filename);
                changed = false;
            }
            catch (Exception e)
            {
                Log.Instance.AddException(e);
                //throw; //Need to catch this one!
            }
            finally
            {
                if (websites == null)
                    websites = new BindingList<Website>();
                websites.ListChanged += new ListChangedEventHandler(websites_ListChanged);
            }
        }

        void websites_ListChanged(object sender, ListChangedEventArgs e)
        {
            changed = true;
        }

        public void Save()
        {
            try
            {
                Global.XMLSerialize(filename, websites);
                changed = false;
            }
            catch (Exception e)
            {
                Log.Instance.AddException(e);
                throw; //Catch
            }
        }

        public void Reload()
        {
            Load();
            changed = true;
        }

        #endregion
    }
}
